<?php
namespace App\Lib\Request;
use function GuzzleHttp\Psr7\str;


/**
 * @package App\Lib\Request
 * @method get($url,$params=[])
 * @method post($url,$data)
 * @method delete($url, $params=[])
 * @method put($url,$data)
 */
class Client
{
    protected $error;
    protected $method = "GET";
    protected $data = [];
    protected $url;
    protected $header = [];
    public $server;
    private $rawResponse = [];

    /**
     * @return mixed
     */
    public function getRawResponse()
    {
        return $this->rawResponse;
    }

    public function setUrl($url)
    {
        $this->url = $url;
        return $this;
    }

    public function getUrl()
    {
        return $this->url;
    }

    /**
     * @param mixed $data
     * @return $this
     */
    public function setData($data)
    {
        $this->bindParams($data);
        if ("POST" == $this->method || "PUT" == $this->method) {
            $this->data = $data;
        } else {
            if (strpos($this->url, "?") === false) {
                $this->url .= "?" . $this->encodeData($data);;
            } else {
                $this->url .= "&" . $this->encodeData($data);
            }
        }
        return $this;
    }

    /**
     * @param string $method
     * @return $this
     */
    public function setMethod($method)
    {
        $this->method = strtoupper($method);
        return $this;
    }


    public function __call($name, $arguments)
    {
        $this->setMethod($name);
        foreach ($arguments as $arg) {
            if (is_string($arg)) {
                $this->url = $arg;
            } elseif (is_array($arg)) {
                $this->setData($arg);
            }
        }
        return $this->curl();
    }

    /**
     * @return ResultObject|bool
     * @throws \Exception
     */
    public function curl()
    {
        $this->server = rtrim($this->server, "/") . "/";
        $this->url =  ltrim($this->url, "/");
        $http = curl_init();
        curl_setopt($http, CURLOPT_RETURNTRANSFER, true);
        $url = join('/', [rtrim($this->server, '/'), ltrim($this->url, '/')]);
        curl_setopt($http, CURLOPT_URL, $url);
        curl_setopt($http, CURLOPT_HEADER, 0);
        curl_setopt($http, CURLOPT_CUSTOMREQUEST, $this->method);
        curl_setopt($http, CURLOPT_TIMEOUT, 200);
        if ($this->method == "POST") {
            curl_setopt($http, CURLOPT_POST, true);
            if (empty($this->data)) {
                $this->data['___request_id'] = "___request_" . time();
            }
            $data =  json_encode($this->data);
            curl_setopt($http, CURLOPT_HTTPHEADER, [
                'content-type:application/json',
                'content-length:' . strlen($data)
            ]);
            curl_setopt($http, CURLOPT_POSTFIELDS, $data);
        }
        $res = curl_exec($http);
        $httpinfo = curl_getinfo($http);
        curl_close($http);
        unset($http);
        if ($httpinfo['http_code'] > 299 && $httpinfo['http_code'] == 500) {
            var_dump($res);
            return false;
        }
        $arr = json_decode($res, true);
        if (json_last_error() > 0) {

            throw new \Exception("请求失败,
            路径:" . $url .
            ";参数:" . \GuzzleHttp\json_encode($this->data) .
            ";返回:".(string) $res);
        }
        //恢复
        $this->reset();
        return new ResultObject($arr);
    }

    // 重置
    protected function reset()
    {
        $this->setData([]);
        $this->setMethod("GET");
        $this->setUrl("");
        $this->rawResponse = "";
        $this->header = "";
    }


    protected function encodeData($raw)
    {
        $url = http_build_query($raw);
        return $url;
    }

    protected function bindParams(&$data)
    {
        $params = explode("?", $this->url);
        if (strpos($params[0], ":") === false) {
            return true;
        }
        $url = explode("/", $params[0]);
        try {
            foreach ($url as $k => $item) {
                $item = trim($item);
                if (strpos($item, ":") === 0) {
                    $url[$k] = $data[$item];
                    unset($data[$item]);
                }
            }
        } catch (\Exception $e) {
            throw new \Exception("URL参数绑定错误");
        }
        $this->url = isset($params[1]) ? implode("?", [implode("/", $url), $params[1]]) : implode("/", $url);
    }


}
